﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using SDF.Core;
using SDF.Plugin.Misc.DynamicEntity.Domain;
using SDF.Core.Data;
using SDF.Plugin.Misc.DynamicEntity.Data;
using SDF.Data;
using SDF.Services.Events;
using System.Transactions;

namespace SDF.Plugin.Misc.DynamicEntity.Services
{
    public class DynamicEntityService : IDynamicEntityService
    {
        private readonly DataContextDynamicEntity _dbContext;
        private readonly IRepository<DynamicEntityHeader> _entityRepository;
        private readonly IRepository<DynamicEntityItem> _itemRepository;
        private readonly IEventPublisher _eventPublisher;

        public DynamicEntityService(
            DataContextDynamicEntity dbContext,
            IRepository<DynamicEntityHeader> entityRepository,
            IRepository<DynamicEntityItem> itemRepository,
            IEventPublisher eventPublisher)
        {
            this._dbContext = dbContext;
            this._entityRepository = entityRepository;
            this._itemRepository = itemRepository;
            this._eventPublisher = eventPublisher;
        }

        #region Header
        public void InsertEntity(DynamicEntityHeader dynamicEntity)
        {
            _entityRepository.Insert(dynamicEntity);

            //event notification
            _eventPublisher.EntityInserted(dynamicEntity);
        }

        public void UpdateEntityHeader(DynamicEntityHeader header)
        {
            _entityRepository.Update(header);

            _eventPublisher.EntityUpdated(header);
        }

        public void DeleteEntities(IList<DynamicEntityHeader> dynamicEntities)
        {
            dynamicEntities.NullCheck("dynamicEntities");

            var list_tobeDel = new List<DynamicEntityHeader>();
            dynamicEntities.ToList().ForEach(entity =>
            {
                entity.Fields.ToList().ForEach(f =>
                {
                    if (f.ReferenceEntity != null)
                        list_tobeDel.Add(f.ReferenceEntity);
                });
            });

            _entityRepository.Delete(dynamicEntities.Union(list_tobeDel));

            dynamicEntities.ToList().ForEach(entity => _eventPublisher.EntityDeleted(entity));
        }

        public DynamicEntityHeader GetEntityById(int id)
        {
            return _entityRepository.GetById(id);
        }

        public IList<DynamicEntityHeader> GetEntitiesByIds(int[] ids)
        {
            ids.NullCheck("ids");
            ids.Any().FalseThrow("ids不能为空");
            (ids.Count() > 50).TrueThrow("不能查询过多行项目");

            return _entityRepository.Table.Where(p => ids.Contains(p.Id)).ToList();
        }

        public IPagedList<DynamicEntityHeader> Query(int projectId = 0, int languageId = 0,
            int pageIndex = 0, int pageSize = int.MaxValue, bool showDel = false, bool showRefer = false, string name = "", string codeName = "")
        {
            var query = _entityRepository.Table;

            if (!showDel)
                query = query.Where(p => p.Delete.Equals(false));

            //这样拼接出的SQL效率不高，考虑在Header表里添加"是否引用实体"标识
            if (showRefer == false)
                query = query.Where(p => p.ReferBy == null);

            if (!name.IsNullOrEmpty())
                query = query.Where(p => p.Name.Contains(name));

            if (!codeName.IsNullOrEmpty())
                query = query.Where(p => p.CodeName.Contains(codeName));

            query = query.OrderByDescending(p => p.CreateTimeOnUtc);

            var result = new PagedList<DynamicEntityHeader>(query, pageIndex, pageSize);
            return result;
        }

        #endregion

        #region Item
        public DynamicEntityItem GetEntityItemById(int id)
        {
            return _itemRepository.GetById(id);
        }

        public IList<DynamicEntityItem> GetItemsByIds(int[] itemIds)
        {
            itemIds.NullCheck("itemIds");
            itemIds.Any().FalseThrow("itemIds不能为空");
            (itemIds.Count() > 50).TrueThrow("不能查询过多行项目");

            var query = _itemRepository.Table.Where(p => itemIds.Contains(p.Id));

            return query.ToList();
        }

        public IList<DynamicEntityItem> GetAllItemsByHeaderId(int headerId)
        {
            var query = _itemRepository.TableNoTracking.Where(p => p.HeaderId.Equals(headerId)).OrderBy(p => p.SortNo);

            return query.ToList();
        }

        public void InsertEntityItem(DynamicEntityItem item)
        {
            item.NullCheck("item");
            _itemRepository.Insert(item);

            //_eventPublisher.EntityInserted()
        }

        public void InsertEntityItems(IEnumerable<DynamicEntityItem> models)
        {
            models.NullCheck("models");

            _itemRepository.Insert(models);
        }

        public void UpdateEntityItem(DynamicEntityItem item)
        {
            item.NullCheck("item");
            _itemRepository.Update(item);
        }

        public void DeleteEntityItem(DynamicEntityItem item)
        {
            item.NullCheck("item");

            if (item.ReferenceEntity != null)
            {
                _entityRepository.Delete(item.ReferenceEntity);
            }

            _itemRepository.Delete(item);
        }

        public void DeleteEntityItem(IList<DynamicEntityItem> items)
        {
            items.NullCheck("items");

            var list_tobeDel = new List<DynamicEntityHeader>();
            items.ToList().ForEach(item =>
            {
                if (item.ReferenceEntity != null)
                {
                    list_tobeDel.Add(item.ReferenceEntity);
                }
            });

            _entityRepository.Delete(list_tobeDel);
            _itemRepository.Delete(items);
        }

        #endregion
    }
}